package com.k.sshm.boot.feature.mvc.minio.controller;

import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

@Slf4j
@RestController
public class BootControl {
    @Autowired
    private MinioClient minioClient;
    private String bucket = "123";

    @PostMapping(value = "/upload")
    @ResponseBody
    String upload(@RequestParam("file") MultipartFile file) throws Exception {
        String name = file.getOriginalFilename();
        long size = file.getSize();
        File uploadFile = asFile(file.getInputStream());
        int imgHeight = getImgHeight(uploadFile);
        int imgWidth = getImgWidth(uploadFile);
        uploadFile(file);
        return "ok";
    }

    public String uploadFile(MultipartFile file) throws Exception {
        String fileName = extractFilename(file);       //对文件名进行编码
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(bucket)   //储存桶名称
                .object(fileName)                      //文件路径加文件名
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build();
        minioClient.putObject(args);                        //上传文件
        //返回上传的路径
        return fileName;
    }

    public static final String extractFilename(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        return fileName;
    }

    public static File asFile(InputStream inputStream) throws IOException {
        File tmp = File.createTempFile("temp", ".tmp");
        OutputStream os = new FileOutputStream(tmp);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        inputStream.close();
        return tmp;
    }


    /**
     * 获取图片宽度
     *
     * @param file 图片文件
     * @return 宽度
     */
    public static int getImgWidth(File file) {
        InputStream is = null;
        BufferedImage src = null;
        int ret = -1;
        try {
            is = new FileInputStream(file);
            src = javax.imageio.ImageIO.read(is);
            ret = src.getWidth(null); // 得到源图宽
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }


    /**
     * 获取图片高度
     *
     * @param file 图片文件
     * @return 高度
     */
    public static int getImgHeight(File file) {
        InputStream is = null;
        BufferedImage src = null;
        int ret = -1;
        try {
            is = new FileInputStream(file);
            src = javax.imageio.ImageIO.read(is);
            ret = src.getHeight(null); // 得到源图高
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }


    //实现Spring Boot 的文件下载功能，映射网址为/download
    @PostMapping("/down")
    public String downloadFile(HttpServletRequest request,
                               HttpServletResponse response, @RequestParam("fileName") String fileName) throws Exception {
        File file;
        //设置文件路径
        try (InputStream stream = minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucket)
                        .object(fileName)
                        .build())) {
            file = asFile(stream);
        }


        // 如果文件名存在，则进行下载
        if (file.exists()) {
            // 配置文件下载
            //response.setHeader("content-type", "application/octet-stream");
            //response.setContentType("application/octet-stream");
            response.setContentType("application/force-download");// 设置强制下载不打开
            // 下载文件能正常显示中文
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            // 实现文件下载
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
                log.info("Download the song successfully!");
            } catch (Exception e) {
                log.info("Download the song error!", e);
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }

}
